package scijava.stats;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class CDF {
	
	
	/**
	 * Function that dumps a CDF of the supplied list of doubles to a file
	 * specified by a string.
	 * 
	 * @param vals
	 *            - a non-empty list of doubles
	 * @param fileName
	 *            - the file the CDF will be writen to in CSV format
	 * @throws IOException
	 *             - if there is an error writting to the file matching the file
	 *             name
	 */
	public static void printCDF(List<Double> origVals, String fileName) throws IOException {
		/*
		 * CDFs over empty lists don't really make sense
		 */
		if (origVals.size() == 0) {
			throw new RuntimeException("Asked to build CDF of an empty list!");
		}

		/*
		 * Clone the list to avoid the side effect of sorting the original list
		 */
		List<Double> vals = new ArrayList<Double>(origVals.size());
		for (double tDouble : origVals) {
			vals.add(tDouble);
		}

		Collections.sort(vals);
		double fracStep = 1.0 / (double) vals.size();
		double currStep = 0.0;

		BufferedWriter outFile = new BufferedWriter(new FileWriter(fileName));

		for (int counter = 0; counter < vals.size(); counter++) {
			currStep += fracStep;
			if (counter >= vals.size() - 1 || vals.get(counter) != vals.get(counter + 1)) {
				// if (vals.get(counter) != vals.get(counter + 1) && counter <=
				// vals.size() + 1) {
				outFile.write("" + currStep + "," + vals.get(counter) + "\n");
				System.out.print("" + currStep + "," + vals.get(counter) + "\n");
			}
		}

		outFile.close();
	}
	
	public static void printCDFs(List<Collection<Double>> origVals, String fileName) throws IOException{
		if(origVals == null || origVals.size() == 0){
			throw new RuntimeException("Asked to build CDFs of empty or null list!");
		}
		
		List<List<Double>> copiedLists = new ArrayList<List<Double>>(origVals.size());
		List<Double> stepSize = new ArrayList<Double>(origVals.size());
		int maxSize = 0;
		for(Collection<Double> tCollection: origVals){
			/*
			 * Skip empty lists
			 */
			if(tCollection.size() == 0){
				continue;
			}
			
			maxSize = Math.max(maxSize, tCollection.size());
			ArrayList<Double> tempList = new ArrayList<Double>(tCollection.size());
			tempList.addAll(tCollection);
			Collections.sort(tempList);
			copiedLists.add(tempList);
			stepSize.add(1.0 / (double)tempList.size());
		}
		
		BufferedWriter outBuff = new BufferedWriter(new FileWriter(fileName));
		for(int step = 0; step < maxSize; step++){
			StringBuilder outStrBuilder = new StringBuilder();
			for(int listPos = 0; listPos < copiedLists.size(); listPos++){
				List<Double> currentList = copiedLists.get(listPos);
				
				/*
				 * Handle the case when this list is shorter than some of the others
				 */
				if(currentList.size() <= step){
					outStrBuilder.append(",,");
					continue;
				}
				
				double currentFraction = stepSize.get(listPos) * (double)(step + 1);
				double currentValue = currentList.get(step);
				outStrBuilder.append(currentFraction);
				outStrBuilder.append(",");
				outStrBuilder.append(currentValue);
				outStrBuilder.append(",");
			}
			outStrBuilder.replace(outStrBuilder.length() - 1, outStrBuilder.length(), "\n");
			outBuff.write(outStrBuilder.toString());
		}
		outBuff.close();
	}

}
